package com.lzp.java.concurrent.collection.concurrenthashmap;

import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author lzp
 * @Description: 虽然使用ConcurrentHashMap，组合操作仍然不能保证线程安全。
 * @date 2021/2/28
 */
public class OptionsNotSafe implements Runnable {
    /**
     * map容器
     */
    private static ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

    public static void main(String[] args) throws InterruptedException {
        map.put("sum", 0);
        Thread thread1 = new Thread(new OptionsNotSafe());
        Thread thread2 = new Thread(new OptionsNotSafe());
        thread1.start();
        thread2.start();
        thread1.join();
        thread2.join();
        System.out.println(map.get("sum")); // 结果不是20000
    }

    @Override
    public void run() {
        for (int i = 0; i < 10000; i++) {
            /**
             * 使用ConcurrentHashMap只能保证对于map的put、get操作是线程安全的，而组合操作不能保证线程安全，例如a++。
             */
            // Integer old = map.get("sum");
            // map.put("sum", old + 1);
            // 也可以通过synchronized同步代码块解决，但是会破坏ConcurrentHashMap思想。
            while (true){
                Integer old = map.get("sum");
                Integer newVal = old + 1;
                if (map.replace("sum", old, newVal)) {
                    break;
                }
            }
        }
    }
}
